{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pylab as plt\n",
    "np.random.seed(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets begin by generating random data with 3 dimensions with 40 samples . We will have two class with 20 samples per class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "vec1 = np.array([0, 0, 0])\n",
    "mat1 = np.eye(3)\n",
    "sample_for_class1 = np.random.multivariate_normal(vec1, mat1, 20).T\n",
    "\n",
    "assert sample_for_class1.shape == (3, 20), \"The dimension of the sample_for_class1 matrix is not 3x20\"\n",
    "\n",
    "vec2 = np.array([1, 1, 1])\n",
    "mat2 = np.eye(3)\n",
    "sample_for_class2 = np.random.multivariate_normal(vec2, mat2, 20).T\n",
    "\n",
    "assert sample_for_class2.shape == (3, 20), \"The dimension of the sample_for_class2 matrix is not 3x20\"\n",
    "\n",
    "all_data = np.concatenate((sample_for_class1, sample_for_class2), axis=1)\n",
    "\n",
    "assert all_data.shape == (3, 40), \"The dimension of the all_data matrix is not 3x20\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.41667492 0.69848315 0.49242335] \n",
      " [[0.41667492]\n",
      " [0.69848315]\n",
      " [0.49242335]]\n"
     ]
    }
   ],
   "source": [
    "mean_dim1 = np.mean(all_data[0, :])\n",
    "mean_dim2 = np.mean(all_data[1, :])\n",
    "mean_dim3 = np.mean(all_data[2, :])\n",
    "\n",
    "mean_vector = np.array([[mean_dim1], [mean_dim2], [mean_dim3]])\n",
    "\n",
    "print(mean_vector.reshape(-1), '\\n', mean_vector)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.62434536],\n",
       "       [-0.61175641],\n",
       "       [-0.52817175]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "all_data[:, 0].reshape(3, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Scatter Matrix is :\n",
      " [[38.4878051  10.50787213 11.13746016]\n",
      " [10.50787213 36.23651274 11.96598642]\n",
      " [11.13746016 11.96598642 49.73596619]]\n"
     ]
    }
   ],
   "source": [
    "scatter_matrix = np.zeros((3,3))\n",
    "for i in range(all_data.shape[1]):\n",
    "    scatter_matrix += (all_data[:, i].reshape(3, 1) - mean_vector).dot(\n",
    "        (all_data[:, i].reshape(3, 1) - mean_vector).T)\n",
    "print('The Scatter Matrix is :\\n', scatter_matrix)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Eigenvalues and Eigenvectors\n",
    "\n",
    "$$\n",
    "Ax = \\lambda x\n",
    "$$\n",
    "\n",
    "Where A denotes the matrix , x denotes the eigenvector and $\\lambda$ denotes the eigenvalues.\n",
    "\n",
    "\n",
    "A Eigenvector of a matrix (which can be seen as a linear transformation of matrix) is the condensed vector which summarizes one axes of the matrix.\n",
    "\n",
    "A matrix can have more than one eigenvector , and at max d eigenvectors if matrix is of dimention d X d.\n",
    "\n",
    "n x n matrix could have n eigenvectors, each one representing its line of action in one dimension\n",
    "\n",
    "\n",
    "The eigenvectors and eigenvalues of a covariance (or correlation) matrix represent the \"core\" of a PCA: The eigenvectors (principal components) determine the directions of the new feature space, and the eigenvalues determine their magnitude. In other words, the eigenvalues explain the variance of the data along the new feature axes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([65.16936779, 32.69471296, 26.59620328]),\n",
       " array([[-0.49210223, -0.64670286,  0.58276136],\n",
       "        [-0.47927902, -0.35756937, -0.8015209 ],\n",
       "        [-0.72672348,  0.67373552,  0.13399043]]))"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eig_val, eig_vec = np.linalg.eig(scatter_matrix)\n",
    "eig_val, eig_vec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.49210223 -0.64670286  0.58276136]\n",
      "1.0000000000000013\n",
      "[-0.47927902 -0.35756937 -0.8015209 ]\n",
      "0.9999999999999992\n",
      "[-0.72672348  0.67373552  0.13399043]\n",
      "0.9999999999999997\n"
     ]
    }
   ],
   "source": [
    "for ev in eig_vec:\n",
    "    print(ev)\n",
    "    print(ev[0]**2 + ev[1]**2 + ev[2]**2)\n",
    "    np.testing.assert_array_almost_equal(1.0, np.linalg.norm(ev))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(65.16936779078195, array([-0.49210223, -0.47927902, -0.72672348])), (32.69471296321799, array([-0.64670286, -0.35756937,  0.67373552])), (26.596203282097097, array([ 0.58276136, -0.8015209 ,  0.13399043]))]\n",
      "(65.16936779078195, array([-0.49210223, -0.47927902, -0.72672348]))\n",
      "(32.69471296321799, array([-0.64670286, -0.35756937,  0.67373552]))\n",
      "(26.596203282097097, array([ 0.58276136, -0.8015209 ,  0.13399043]))\n"
     ]
    }
   ],
   "source": [
    "eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(len(eig_val))]\n",
    "print(eig_pairs)\n",
    "\n",
    "# We then Sort list of tuples by the eigenvalue\n",
    "eig_pairs.sort(key=lambda x: x[0], reverse=True)\n",
    "\n",
    "# verify that the list is correctly sorted by decreasing eigenvalues\n",
    "for i in eig_pairs:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrix W:\n",
      " [[-0.49210223 -0.64670286]\n",
      " [-0.47927902 -0.35756937]\n",
      " [-0.72672348  0.67373552]]\n"
     ]
    }
   ],
   "source": [
    "matrix_w = np.hstack((eig_pairs[0][1].reshape(3,1), eig_pairs[1][1].reshape(3,1)))\n",
    "print('Matrix W:\\n', matrix_w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.12230714,  1.78582073, -0.72564846,  0.91911067, -0.48120545,\n",
       "         1.26186049,  0.49974121, -1.36060904, -0.02630959,  0.20346559,\n",
       "         1.02990798,  0.74684543, -0.76873682,  0.37184198, -0.48040292,\n",
       "        -1.30433953, -0.57308381,  0.9748035 , -0.78806782, -1.23832629,\n",
       "        -2.30009539, -1.73062935, -4.57170736,  0.04785487, -2.42616804,\n",
       "        -1.15792646, -2.01497976, -1.98672036, -1.36534078, -2.76311357,\n",
       "        -2.1041081 , -1.64296088, -1.09921946, -2.71718701, -1.38545546,\n",
       "        -1.44331476, -0.58485289, -1.63411201, -1.21353834, -1.73760916],\n",
       "       [-1.18757151, -1.16617976, -0.64124251, -1.74952646,  1.10969495,\n",
       "         0.18151348, -0.97722286, -0.72412904, -0.42090149,  1.05827266,\n",
       "         0.12619324,  0.77808138,  1.75701561, -1.00931473, -0.08774954,\n",
       "         1.75869787, -0.09616466,  0.4009659 ,  0.49058694, -0.10791262,\n",
       "         0.05492635, -0.3633537 , -0.13330484,  0.74907576, -0.53466984,\n",
       "         1.6445517 , -0.90160187,  0.00885182, -0.95318056,  0.14270558,\n",
       "        -1.4249294 , -0.01678979, -0.54147105,  0.20291779, -1.54140242,\n",
       "        -1.3474191 , -1.09515232, -1.41599875, -0.11407398,  0.58889408]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "transformed = matrix_w.T.dot(all_data)\n",
    "transformed "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert transformed.shape == (2,40), \"The matrix is not 2x40 dimensional.\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f3dae4b4f28>"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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GKDBKqGVlJmsXr2alStXsmDBgonf0ICPBiRJM8L999/P1ltvbRJQIyLYeuutp9VKYiIgSZoxTALWN93fiYmAJElTdOSRR/LJT36yLee+9tpr2WOPPdh4443bdg2wj4AkST1pq6224rOf/Szf+c532nodWwQkSf1pZAQGBmDWrGI7MjLtU375y19mp512Yuedd+YNb3jDOsdOPPFEnv/857Pzzjtz0EEHsWbNGgC+8Y1v8KxnPYudd96ZvfbaC4ClS5ey6667sssuu7DTTjtx/fXXr3etbbbZhuc///lTHg3QLBMBSVL/GRmBhQth+XLILLYLF04rGVi6dCkf/ehHOe+887j88sv5zGc+s87xAw88kEsuuYTLL7+cpz/96Zx00kkAHHXUUZxzzjlcfvnlnHnmmQCccMIJHH744Vx22WUsWbKEHXbYYeqfdZpMBCRJ/WfRIii/kT9izZqifIrOO+88Dj74YObMmQMUTfe1rrrqKl70ohfx7Gc/m5GREZYuXQrAnnvuyaGHHsqJJ57Iww8/DMAee+zB0UcfzTHHHMPy5cvZdNNNpxzXdJkISJL6z4oVkytvgUMPPZTPf/7zXHnllXzoQx96ZEjfCSecwEc/+lFuvvlmnve857F69Wpe//rXc+aZZ7Lpppuy//77c95553H88cezyy67sMsuu/D73/++bXHWMxGQJPWfefMmV96El7zkJXzjG99g9erVANx1113rHL/vvvvYbrvtePDBBxmpeQRx4403sttuu3HUUUcxd+5cbr75Zm666SZ23HFH3v3ud3PAAQdwxRVX8M53vpPLLruMyy67jCc+8YlTjnOyHDUgSeo/ixcXfQJqHw/Mnl2UT9Ezn/lMFi1axN57780GG2zAc57zHAYGBh45/pGPfITddtuNuXPnsttuu3HfffcB8O///u9cf/31ZCYvfelL2XnnnTnmmGM47bTT2Gijjdh222354Ac/uN71brvtNgYHB7n33nuZNWsWxx13HFdffTWbb775lD9DI5GZLT1hrxocHMwlS5Z0OwxJIyPFc9oVK4pvZ4sXw9BQt6PSDHDNNdfw9Kc/vfk3VOjvWqPfTURcmpmDE73XRwOSOqcNPbmnFUuLh5apxwwNwbJlsHZtse3TJGC6TAQkdU4benJPSS8lJFKXmQhI6pwu9ORuqFcSEqkHmAhI6pw29OSekl5J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\n",
      "text/plain": [
       "<Figure size 576x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize = (8,8))\n",
    "ax = fig.add_subplot(1,1,1) \n",
    "ax.set_xlabel('Principal Component 1', fontsize = 15)\n",
    "ax.set_ylabel('Principal Component 2', fontsize = 15)\n",
    "ax.set_title('2 component PCA', fontsize = 20)\n",
    "\n",
    "targets = ['class-1', 'class-2']\n",
    "colors = ['r', 'b']\n",
    "ax.scatter(transformed[0, 0:20], transformed[1, 0:20], c=colors[0], label=targets[0])\n",
    "ax.scatter(transformed[0, 20:], transformed[1, 20:], c=colors[1], label=targets[1])\n",
    "ax.legend(targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# References\n",
    "\n",
    "[CSDN-1](https://blog.csdn.net/weixin_38314865/article/details/84190175)\n",
    "\n",
    "[Plt](https://plotly.com/python/v3/ipython-notebooks/principal-component-analysis/)\n",
    "\n",
    "[PCA](https://medium.com/@raghavan99o/principal-component-analysis-pca-explained-and-implemented-eeab7cb73b72)\n",
    "\n",
    "[eigenvector](https://pathmind.com/wiki/eigenvector)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![2D to 1D](https://gitee.com/lidongai/assets_blog_post/raw/master/Note/Math/pca-1.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
